import os
from PIL import Image, ImageDraw, ImageFont
from reportlab.lib.pagesizes import A1
from reportlab.pdfgen import canvas
from reportlab.lib import colors
from reportlab.platypus import Paragraph, SimpleDocTemplate, Spacer, Image as RLImage
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT
from typing import Dict, List
import json
import config
import shutil


class PosterCreator:
    def __init__(self):
        self.output_dir = config.OUTPUT_DIR
        os.makedirs(self.output_dir, exist_ok=True)

    def _parse_color(self, color_str):
        """Parse color string to reportlab color."""
        if color_str.startswith('#'):
            # Convert hex to RGB
            r = int(color_str[1:3], 16) / 255
            g = int(color_str[3:5], 16) / 255
            b = int(color_str[5:7], 16) / 255
            return colors.Color(r, g, b)
        else:
            # Use named color
            return getattr(colors, color_str, colors.black)

    def _process_image_for_poster(self, img_path, target_width=None, target_height=None):
        """处理图像以适应海报布局"""
        try:
            img = Image.open(img_path)
            img_width, img_height = img.size
            aspect_ratio = img_width / img_height
            
            # 处理竖版图像
            if aspect_ratio < 1:  # 竖版图像
                if not target_width:
                    target_width = 800
                if not target_height:
                    target_height = int(target_width / aspect_ratio)
                
                # 调整图像大小
                img = img.resize((target_width, target_height), Image.LANCZOS)
                
                # 保存处理后的图像为JPG格式
                file_ext = os.path.splitext(img_path)[1].lower()
                if file_ext == '.png':
                    processed_path = img_path.replace('.png', '_processed.jpg')
                else:
                    processed_path = img_path.replace(file_ext, '_processed.jpg')
                
                img.save(processed_path, 'JPEG', quality=95)
                return processed_path
            
            return img_path
        except Exception as e:
            print(f"处理图像时出错: {str(e)}")
            return img_path

    def create_poster(self, content: Dict, image_paths: List[str], style_description: str, request_id: str) -> str:
        """Create the final academic poster PDF."""
        pdf_path = os.path.join(self.output_dir, f"{request_id}.pdf")
        preview_path = os.path.join(self.output_dir, f"{request_id}_preview.png")
    
        # 预处理图像
        processed_image_paths = []
        for img_path in image_paths:
            try:
                processed_path = self._process_image_for_poster(img_path)
                processed_image_paths.append(processed_path)
            except Exception as e:
                print(f"预处理图像时出错 {img_path}: {str(e)}")
                processed_image_paths.append(img_path)
        
        # 使用处理后的图像路径
        image_paths = processed_image_paths

        # Extract style guidance
        style_guidance = content.get("style_guidance", {})
        if isinstance(style_guidance, str):
            # Try to parse style guidance if it's a string
            try:
                style_guidance = json.loads(style_guidance)
            except:
                # Use default styling if parsing fails
                style_guidance = {
                    "colors": {"primary": "#003366", "secondary": "#990000", "background": "#FFFFFF",
                               "text": "#333333"},
                    "typography": {"title": "Arial-Bold", "headings": "Arial-Bold", "body": "Arial"},
                    "layout": "Standard academic poster with columns"
                }

        # Set up colors
        colors_dict = style_guidance.get("colors", {})
        if not colors_dict:
            colors_dict = {"primary": "#003366", "secondary": "#990000", "background": "#FFFFFF", "text": "#333333"}

        primary_color = self._parse_color(colors_dict.get("primary", "#003366"))
        secondary_color = self._parse_color(colors_dict.get("secondary", "#990000"))
        background_color = self._parse_color(colors_dict.get("background", "#FFFFFF"))
        text_color = self._parse_color(colors_dict.get("text", "#333333"))

        # 使用竖版页面尺寸 (A1 竖版)
        from reportlab.lib.pagesizes import portrait, A1
        doc = SimpleDocTemplate(pdf_path, pagesize=portrait(A1),
                                rightMargin=72, leftMargin=72,
                                topMargin=72, bottomMargin=72)

        # Create styles
        styles = getSampleStyleSheet()

        # Custom styles based on style guidance
        title_style = ParagraphStyle(
            name='PosterTitle',
            parent=styles['Title'],
            fontSize=48,
            alignment=TA_CENTER,
            textColor=primary_color,
            spaceAfter=30
        )

        heading_style = ParagraphStyle(
            name='PosterHeading',
            parent=styles['Heading1'],
            fontSize=28,
            textColor=primary_color,
            spaceAfter=12
        )

        body_style = ParagraphStyle(
            name='PosterBody',
            parent=styles['Normal'],
            fontSize=20,
            textColor=text_color,
            spaceAfter=12
        )

        # Build poster content
        elements = []

        # Title
        title_text = content.get("title", "Research Poster")
        elements.append(Paragraph(title_text, title_style))
        elements.append(Spacer(1, 20))

        # Authors
        authors = content.get("authors", [])
        if authors:
            if isinstance(authors, list):
                authors_text = ", ".join(authors)
            else:
                authors_text = authors
            elements.append(Paragraph(authors_text, body_style))
            elements.append(Spacer(1, 30))

        # 使用单列布局而非双列布局
        from reportlab.platypus import Table, TableStyle

        # 添加图像 - 在内容前添加图像
        for i, img_path in enumerate(image_paths):
            if i < 1:  # 限制为1张图像
                try:
                    # 检查图像尺寸并适配竖版比例
                    img_obj = Image.open(img_path)
                    img_width, img_height = img_obj.size
                    
                    # 限制图像尺寸，防止过大
                    max_width = min(doc.width * 0.8, 800)  # 限制最大宽度
                    max_height = min(doc.height * 0.4, 1000)  # 限制最大高度
                    
                    # 计算合适的显示尺寸，确保图像宽度适合页面且不超过最大限制
                    display_width = min(max_width, doc.width * 0.8)
                    aspect_ratio = img_width / img_height
                    display_height = min(max_height, display_width / aspect_ratio)
                    
                    # 如果高度超出限制，重新调整宽度
                    if display_height > max_height:
                        display_height = max_height
                        display_width = display_height * aspect_ratio
                    
                    img = RLImage(img_path, width=display_width, height=display_height)
                    elements.append(img)
                    elements.append(Spacer(1, 10))
                    caption = f"Figure 1: Visualization of research results"
                    elements.append(Paragraph(caption, ParagraphStyle(
                        name='Caption',
                        parent=body_style,
                        fontSize=16,
                        alignment=TA_CENTER
                    )))
                    elements.append(Spacer(1, 20))
                except Exception as e:
                    print(f"Error adding image {img_path}: {str(e)}")

        # 内容部分 - 单列布局
        # Introduction/Background
        intro = content.get("introduction", [])
        if intro:
            elements.append(Paragraph("Introduction", heading_style))
            if isinstance(intro, list):
                for item in intro:
                    elements.append(Paragraph(f"• {item}", body_style))
            else:
                elements.append(Paragraph(intro, body_style))
            elements.append(Spacer(1, 20))

        # Objectives
        objectives = content.get("objectives", [])
        if objectives:
            elements.append(Paragraph("Research Objectives", heading_style))
            if isinstance(objectives, list):
                for item in objectives:
                    elements.append(Paragraph(f"• {item}", body_style))
            else:
                elements.append(Paragraph(objectives, body_style))
            elements.append(Spacer(1, 20))

        # Methodology
        methodology = content.get("methodology", [])
        if methodology:
            elements.append(Paragraph("Methodology", heading_style))
            if isinstance(methodology, list):
                for item in methodology:
                    elements.append(Paragraph(f"• {item}", body_style))
            else:
                elements.append(Paragraph(methodology, body_style))
            elements.append(Spacer(1, 20))

        # Results
        results = content.get("results", [])
        if results:
            elements.append(Paragraph("Key Results", heading_style))
            if isinstance(results, list):
                for item in results:
                    elements.append(Paragraph(f"• {item}", body_style))
            else:
                elements.append(Paragraph(results, body_style))
            elements.append(Spacer(1, 20))

        # Conclusions
        conclusions = content.get("conclusions", [])
        if conclusions:
            elements.append(Paragraph("Conclusions", heading_style))
            if isinstance(conclusions, list):
                for item in conclusions:
                    elements.append(Paragraph(f"• {item}", body_style))
            else:
                elements.append(Paragraph(conclusions, body_style))
            elements.append(Spacer(1, 20))

        # References
        references = content.get("references", [])
        if references:
            elements.append(Paragraph("References", heading_style))
            if isinstance(references, list):
                for ref in references:
                    elements.append(Paragraph(f"• {ref}", ParagraphStyle(
                        name='Reference',
                        parent=body_style,
                        fontSize=16
                    )))
            else:
                elements.append(Paragraph(references, ParagraphStyle(
                    name='Reference',
                    parent=body_style,
                    fontSize=16
                )))
            elements.append(Spacer(1, 20))

        # Contact
        contact = content.get("contact", [])
        if contact:
            elements.append(Paragraph("Contact Information", heading_style))
            if isinstance(contact, list):
                for item in contact:
                    elements.append(Paragraph(item, ParagraphStyle(
                        name='Contact',
                        parent=body_style,
                        fontSize=16
                    )))
            else:
                elements.append(Paragraph(contact, ParagraphStyle(
                    name='Contact',
                    parent=body_style,
                    fontSize=16
                )))

        # Build PDF
        doc.build(elements)

        # Create preview image
        try:
            from pdf2image import convert_from_path
            pages = convert_from_path(pdf_path, 300)
            preview_path_jpg = preview_path.replace('.png', '.jpg')
            pages[0].save(preview_path_jpg, 'JPEG', quality=90)
            # 同时保存PNG版本以兼容现有代码
            pages[0].save(preview_path, 'PNG')
        except Exception as e:
            print(f"Error creating preview: {str(e)}")
            # 创建竖版比例的占位预览图
            preview_width = 1080
            preview_height = 1920
            img = Image.new('RGB', (preview_width, preview_height), color=(255, 255, 255))
            d = ImageDraw.Draw(img)
            try:
                font = ImageFont.truetype("Arial", 30)
            except:
                font = ImageFont.load_default()
            
            # 在图像中心添加文本
            text = "海报预览 (生成失败)"
            try:
                text_width = d.textlength(text, font=font)
                position = ((preview_width - text_width) // 2, preview_height // 2)
                d.text(position, text, fill=(0, 0, 0), font=font)
            except AttributeError:
                position = (preview_width // 2, preview_height // 2)
                d.text(position, text, fill=(0, 0, 0), font=font, anchor="mm")
            
            # 保存JPG和PNG两种格式
            preview_path_jpg = preview_path.replace('.png', '.jpg')
            img.save(preview_path_jpg, 'JPEG', quality=90)
            img.save(preview_path, 'PNG')
            img.save(preview_path)

        # Clean up temporary images
        for img_path in image_paths:
            try:
                if os.path.exists(img_path):
                    os.remove(img_path)
            except:
                pass

        return pdf_path